/*--------------------------------------------------------------------------------*/
#ifndef __REF_TO___
#define __REF_TO___
/*--------------------------------------------------------------------------------*/
#include "object.h"
#include "primitives.h"
#include "debug.h"
/*--------------------------------------------------------------------------------*/
template< class _OBJECT_ >
class REF_TO_
{

	// -- PUBLIC

public :

    // .. CONSTRUCTORS

    REF_TO_() : Object( NULL )
    {

    }

    REF_TO_( const _OBJECT_ & other ) : Object( NULL )
    {
    	Set( const_cast < _OBJECT_* >( &other ) );
    }
    
    REF_TO_( const _OBJECT_ * other ) : Object( NULL )
    {
    	Set( const_cast < _OBJECT_* >( other ) );
    }

    REF_TO_( const REF_TO_ & other ) : Object( NULL )
    {
    	Set( other.Object );
    }

    ~REF_TO_()
    {
        Set( NULL );
    }

    // .. METHODS

    VOID New()
    {
    	Set( new _OBJECT_() );
		Object->SetIsAllocated();
    }

    BOOL IsNull() const
    {
        return Object == NULL;
    }

    _OBJECT_ & GetObject()
    {
    	return *Object;
    }

    const _OBJECT_ & GetObject() const
    {
    	return *Object;
    }
    
    _OBJECT_ * GetPointer()
    {
    	return Object;
    }

    const _OBJECT_ * GetPointer() const
    {
    	return Object;
    }

    VOID Set( const _OBJECT_ * object )
	{
		if ( Object )
		{
			Object->RemoveRef();
		}

		if ( object )
		{
			_OBJECT_
				* new_object;

			new_object = const_cast < _OBJECT_* >( object );
			new_object->AddRef();

			Object = new_object;
		}
		else
		{
			Object = NULL;
		}
	}

    VOID SetNull()
    {
    	Set( NULL );
    }

    // .. OPERATORS

    REF_TO_ & operator=( const REF_TO_< _OBJECT_ > & other )
    {
        Set( other.Object );
        return *this;
    }

    REF_TO_ & operator=( const _OBJECT_ * object )
    {
        Set( object );
        return *this;
    }

    BOOL operator==( const _OBJECT_ * object ) const
    {
        return Object == object;
    }

    _OBJECT_ * operator->()
    {
    	DEBUG_Require( Object != NULL );

        return Object;
    }

    _OBJECT_ & operator*()
    {
    	DEBUG_Require( Object != NULL );

        return *Object;
    }

    const _OBJECT_ * operator->() const
    {
    	DEBUG_Require( Object != NULL );

        return Object;
    }

    const _OBJECT_ & operator*() const
    {
    	DEBUG_Require( Object != NULL );

        return *Object;
    }

    template< class _OTHER_ >
    operator REF_TO_<_OTHER_>() const
    {
        return REF_TO_<_OTHER_>( (_OTHER_*)( Object  ) );
    }
    
    template< class _OTHER_ >
    const _OTHER_ & GetObject() const
    {
    	return *( ( _OTHER_* )( Object ) );
    }

    // -- PRIVATE

private :

    // .. ATTRIBUTES

    _OBJECT_ *Object;


};
/*--------------------------------------------------------------------------------*/
#endif

